package com.leige.utils.tool;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

public class ClassResourceUtil {
	private static final Log logger = LogFactory.getLog(ClassResourceUtil.class);
	
	public static void main(String[] args) throws Exception {
			String packageName = "classpath:com.*.internal.*.io";
			List<Class<?>> css = getClassName(packageName);
			PathMatchingResourcePatternResolver p=new PathMatchingResourcePatternResolver();
			Resource[] aa = p.getResources("classpath:conf/spring/**.xml");
			System.out.println(aa.length);
			System.out.println(css);
			
	}


	/**
	 * 获取某包下所有类
	 * @param packageName 包名
	 * @return 类的完整名称
	 */
	public static List<Class<?>> getClassName(String patternPackage) {
		if(patternPackage==null)return null;
		
		patternPackage=patternPackage.trim();
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		List<Class<?>> myclasss = new ArrayList<Class<?>>();
		if(patternPackage.startsWith("classpath:")){
			URL[] urls = ((URLClassLoader) loader).getURLs();
			patternPackage=patternPackage.substring(10).trim().replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*");
			Pattern pattern=Pattern.compile("^"+patternPackage+".*") ;
			for (URL url : urls) {
				File paths = new File(url.getFile());
				if ( paths.isDirectory()) {
					  getClassNameByFile(url.getPath(),pattern,myclasss  );
				} else if (url.getFile().endsWith(".jar")) {
					  getClassNameByJar(url.getPath() , pattern,myclasss );
				}
			}
			return myclasss;
		}else{
			URL url = loader.getResource("");
			patternPackage=patternPackage.replaceAll("\\.", "\\.").replaceAll("\\*", ".*");
			Pattern pattern=Pattern.compile("^"+patternPackage+".*") ;
			File paths = new File(url.getFile());
			if ( paths.isDirectory()) {
				  getClassNameByFile(url.getPath(),pattern,myclasss  );
			} else if (url.getFile().endsWith(".jar")) {
				  getClassNameByJar(url.getPath() , pattern,myclasss );
			} 
			return myclasss;
		}
	}

	 /**
	  * 
	  * @param filePath
	  * @param pattern
	  * @param myClassName
	  */
	private static void getClassNameByFile(String filePath,Pattern  pattern, List<Class<?>> myClassName ) {
		File file = new File(filePath);
		File[] childFiles = file.listFiles();
		if(childFiles==null)return;
		for (File childFile : childFiles) {
			if (childFile.isDirectory()) {
					 getClassNameByFile(childFile.getPath(),pattern, myClassName );
			} else {
				String childFilePath = childFile.getPath();
				if(!childFilePath.endsWith(".class"))
					continue;
				childFilePath=childFilePath.substring(childFilePath.indexOf("\\classes") + 9, childFilePath.lastIndexOf(".")).replace("\\", ".");
				if (pattern.matcher(childFilePath).matches()) {
					matcherClass(childFilePath,myClassName);
				}
			}
		}
	}

	/**
	 * 从jar获取某包下所有类
	 * @param jarFilePath
	 * @param pattern
	 * @param myClassName
	 */
	private static void getClassNameByJar(String jarFilePath,Pattern pattern,List<Class<?>> myClassName ) {
		JarFile jarFile = null;
		try {
			jarFile = new JarFile(jarFilePath);
			Enumeration<JarEntry> entrys = jarFile.entries();
			while (entrys.hasMoreElements()) {
				JarEntry jarEntry = entrys.nextElement();
				String entryName = jarEntry.getName();
				if (entryName.endsWith(".class")) {
					entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
					if (pattern.matcher(entryName).matches()) {
						matcherClass(entryName,myClassName);
					}
				}
			}
			
		} catch (Exception e) {
			logger.debug("",e);
		}finally {
			if(jarFile!=null)
				try {
					jarFile.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					logger.debug("",e);
				}
		}
	}
	private static void matcherClass(String className,List<Class<?>> myClassName){
		try {
			myClassName.add(Class.forName(className));
		} catch (Exception e) {
			logger.debug("",e);
		}
	}
}